package edu.tgc.log;

import org.abyss.common.annotation.Log;
import org.abyss.utils.JsonUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import edu.tgc.entity.log.LogMethod;
import edu.tgc.repository.system.LogMethodRepository;
import edu.tgc.security.SessionUserUtils;

@Order(value = 1)
@Component
@Aspect
public class LogMethodAdvise {

    @Autowired
    private LogMethodRepository logMethodRepository;

    @AfterReturning(value = "execution(* *.*(..)) and @annotation(methodAnnotation)", returning = "retVal")
    public void afterReturning(JoinPoint joinPoint, Log methodAnnotation, Object retVal) {
        String operate = methodAnnotation.value();
        Log classAnnotation = joinPoint.getTarget().getClass().getAnnotation(Log.class);
        if (classAnnotation != null) {
            operate += classAnnotation.value();
        }
        String parameter = JsonUtils.writeValue(joinPoint.getArgs());
        String result = JsonUtils.writeValue(retVal);
        this.logMethodRepository.save(LogMethod.success(SessionUserUtils.getSysUser(), operate, joinPoint, parameter, result));
        Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
        if (logger.isInfoEnabled()) {
            logger.info(operate, joinPoint.getTarget().getClass().toString(), joinPoint.getSignature().getName(), parameter, result);
        }
    }

    @AfterThrowing(value = "execution(* *(..)) and @annotation(methodAnnotation)", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Log methodAnnotation, Throwable e) {
        String operate = methodAnnotation.value();
        Log classAnnotation = joinPoint.getTarget().getClass().getAnnotation(Log.class);
        if (classAnnotation != null) {
            operate += classAnnotation.value();
        }
        String parameter = JsonUtils.writeValue(joinPoint.getArgs());
        this.logMethodRepository.save(LogMethod.failed(SessionUserUtils.getSysUser(), operate, e.getMessage(), joinPoint, parameter));
        Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
        if (logger.isDebugEnabled()) {
            logger.debug(operate, joinPoint.getTarget().getClass().toString(), joinPoint.getSignature().getName(), parameter);
        }
    }
}
